using System;
using GTA;
using GTA.Math;

namespace CustomPeds;

public class OnFootSexScript : Script
{
	public enum Status
	{
		None,
		Sex
	}

	public enum SexType
	{
		None,
		SexOralStand,
		SexStand,
		Sex2Stand,
		SexOralSit,
		SexOral2Sit,
		SexSit,
		SexLie,
		PoleDance,
		RewardDance,
		ExclusiveDanceSingle,
		ExclusiveDanceDouble
	}

	private static SexType sexType;

	private static Status status;

	private static float sexSpeed = 1f;

	private static Ped cloneGirl;

	private static Prop prop1;

	private static Prop prop2;

	private static bool ImmediateStopSex;

	private static int camViewMode;
	
	// 优化：添加Prop管理
	private static bool propsSpawned;
	

	private bool IsDanceShow
	{
		get
		{
			if (sexType == SexType.PoleDance || sexType == SexType.RewardDance || sexType == SexType.ExclusiveDanceSingle || sexType == SexType.ExclusiveDanceDouble)
			{
				return true;
			}
			return false;
		}
	}

	public OnFootSexScript()
	{
		Tick += OnTick;
		// 优化：设置合理的脚本间隔
		Interval = 0;
	}

	private void OnTick(object sender, EventArgs e)
	{
		if (Main.m_Status != Main.MaleStatus.OnFoot || status != Status.Sex)
		{
			return;
		}
		
		try
		{
			if (!IsDanceShow)
			{
				OtherHelper.DisplayHelpTextThisFrame($"~INPUT_CELLPHONE_LEFT~ ~INPUT_CELLPHONE_RIGHT~ {TextSetting.of_HelpText_Rythm}~n~" + $"~INPUT_CONTEXT~ {TextSetting.of_HelpText_Exit}");
				if (Game.IsControlJustPressed(0, Control.Context) || ImmediateStopSex)
				{
					sexSpeed = 0.55f;
					Main.P1.Character.PlayAmbientSpeech1("SEX_CLIMAX", immediately: true);
					Main.P2.Character.PlayAmbientSpeech2("SEX_FINISHED", immediately: true);
					SexSpeedChanges();
					Main.P2.Character.IsSpeechPlayingToEnd();
					Main.P1.Character.IsSpeechPlayingToEnd();
					ImmediateStopSex = true;
					OtherHelper.SetFollowPedCamViewMode(camViewMode);
					StageEnd();
				}
				if (Game.IsControlJustPressed(0, Control.PhoneLeft))
				{
					if (sexSpeed >= 0.55f)
					{
						sexSpeed -= 0.05f;
					}
					else
					{
						sexSpeed = 0.55f;
					}
					SexSpeedChanges();
				}
				if (Game.IsControlJustPressed(0, Control.PhoneRight))
				{
					if (sexSpeed <= 2f)
					{
						sexSpeed += 0.05f;
					}
					else
					{
						sexSpeed = 2f;
					}
					SexSpeedChanges();
				}
				if (Main.P1.Character.GetEntityAnimCurrentTime("misscarsteal2pimpsex", "pimpsex_punter") >= 0.379)
				{
					Main.P1.Character.SetEntityAnimCurrentTime("misscarsteal2pimpsex", "pimpsex_punter", 0f);
					Main.P2.Character.SetEntityAnimCurrentTime("misscarsteal2pimpsex", "pimpsex_hooker", 0f);
				}
			}
			else
			{
				OtherHelper.DisplayHelpTextThisFrame($"~INPUT_CONTEXT~ {TextSetting.of_HelpText_Exit}");
				if (Game.IsControlJustPressed(0, Control.Context) || ImmediateStopSex)
				{
					ImmediateStopSex = true;
					OtherHelper.SetFollowPedCamViewMode(camViewMode);
					StageEnd();
				}
			}
		}
		catch (Exception ex)
		{
			UI.Notify($"性爱脚本错误: {ex.Message}");
		}
	}

	public static void InitSexPlay(SexType _sexType)
	{
		try
		{
			camViewMode = OtherHelper.GetFollowPedCamViewMode();
			sexType = _sexType;
			status = Status.Sex;
			sexSpeed = 1f;
			ImmediateStopSex = false;
			propsSpawned = false;
			
			if (sexType == SexType.SexOralStand)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P2.Character.SetNoCollision(Main.P1.Character, toggle: true);
				Main.P2.Character.Heading = Main.P1.Character.Heading - 180f;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0.55f, 0f));
				Main.P1.Character.TaskPlayAnimLoop("misscarsteal2pimpsex", "pimpsex_punter", -1);
				Main.P2.Character.TaskPlayAnimLoop("misscarsteal2pimpsex", "pimpsex_hooker", -1);
				Main.P2.Character.PlayAmbientSpeech2("SEX_ORAL_FEM", immediately: true);
				Main.P1.Character.PlayAmbientSpeech1("SEX_GENERIC", immediately: true);
				Wait(500);
				Game.FadeScreenIn(500);
			}
			else if (sexType == SexType.SexStand)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P2.Character.SetNoCollision(Main.P1.Character, toggle: true);
				Main.P2.Character.Heading = Main.P1.Character.Heading;
				Main.P2.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(-0.04f, 0.35f, -1.1f));
				Main.P1.Character.TaskPlayAnimLoop("rcmpaparazzo_2", "shag_loop_a", -1);
				Main.P2.Character.TaskPlayAnimLoop("rcmpaparazzo_2", "shag_loop_poppy", -1);
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: true);
				Main.P1.Character.PlayAmbientSpeech1("SEX_GENERIC", immediately: true);
				Wait(500);
				Game.FadeScreenIn(500);
			}
			else if (sexType == SexType.Sex2Stand)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P2.Character.Heading = Main.P1.Character.Heading - 170f;
				Main.P2.Character.SetNoCollision(Main.P1.Character, toggle: true);
				Main.P2.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0.45f, -1.05f));
				Main.P1.Character.TaskPlayAnimLoop("misscarsteal2pimpsex", "shagloop_pimp", -1);
				Main.P2.Character.TaskPlayAnimLoop("misscarsteal2pimpsex", "shagloop_hooker", -1);
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: true);
				Main.P1.Character.PlayAmbientSpeech1("SEX_GENERIC", immediately: true);
				Wait(500);
				Game.FadeScreenIn(500);
			}
			else if (sexType == SexType.SexOralSit)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P1.Character.FreezePosition = true;
				Main.P1.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0f, -1.5f));
				Main.P1.Character.TaskPlayAnimLoop("mini@prostitutes@sexnorm_veh", "bj_loop_male", -1);
				Main.P2.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.85f, 0f, -1f));
				Main.P2.Character.Heading = Main.P1.Character.Heading;
				Main.P2.Character.TaskPlayAnimLoop("mini@prostitutes@sexnorm_veh", "bj_loop_prostitute", -1);
				SpawningProp("prop_patio_lounger1", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, -0.4f, 0f)), new Vector3(0f, 0f, Main.P1.Character.Heading + 180f), ref prop1, dynamic: true, placeOnGround: true, 0.5f);
				SpawningProp("prop_patio_lounger1", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.7f, -0.4f, 0f)), new Vector3(0f, 0f, Main.P1.Character.Heading + 180f), ref prop2, dynamic: true, placeOnGround: true, 0.5f);
				propsSpawned = true;
				Main.P2.Character.PlayAmbientSpeech2("SEX_ORAL_FEM", immediately: true);
				Main.P1.Character.PlayAmbientSpeech1("SEX_GENERIC", immediately: true);
				Wait(500);
				Game.FadeScreenIn(500);
			}
			else if (sexType == SexType.SexOral2Sit)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P1.Character.FreezePosition = true;
				Main.P1.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0f, -1.5f));
				Main.P1.Character.TaskPlayAnimLoop("mini@prostitutes@sexnorm_veh", "bj_loop_male", -1);
				Main.P2.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.15f, 1.02f, -1.1f));
				Main.P2.Character.Heading = Main.P1.Character.Heading + 90f;
				Main.P2.Character.TaskPlayAnimLoop("mini@prostitutes@sexnorm_veh", "bj_loop_prostitute", -1);
				SpawningProp("prop_patio_lounger1", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, -0.3f, 0f)), new Vector3(0f, 0f, Main.P1.Character.Heading + 180f), ref prop1, dynamic: true, placeOnGround: true, 0.5f);
				propsSpawned = true;
				Main.P2.Character.PlayAmbientSpeech2("SEX_ORAL_FEM", immediately: true);
				Main.P1.Character.PlayAmbientSpeech1("SEX_GENERIC", immediately: true);
				Wait(500);
				Game.FadeScreenIn(500);
			}
			else if (sexType == SexType.SexSit)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P2.Character.SetNoCollision(Main.P1.Character, toggle: true);
				Main.P1.Character.FreezePosition = true;
				Main.P1.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0f, -1.5f));
				Main.P1.Character.TaskPlayAnimLoop("mini@prostitutes@sexnorm_veh", "sex_loop_male", -1);
				Main.P2.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.8f, 0.07f, -1f));
				Main.P2.Character.Heading = Main.P1.Character.Heading;
				Main.P2.Character.TaskPlayAnimLoop("mini@prostitutes@sexnorm_veh", "sex_loop_prostitute", -1);
				SpawningProp("prop_patio_lounger1", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, -0.3f, 0f)), new Vector3(0f, 0f, Main.P1.Character.Heading + 180f), ref prop1, dynamic: true, placeOnGround: true, 0.5f);
				propsSpawned = true;
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: true);
				Main.P1.Character.PlayAmbientSpeech1("SEX_GENERIC", immediately: true);
				Wait(500);
				Game.FadeScreenIn(500);
			}
			else if (sexType == SexType.SexLie)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P1.Character.FreezePosition = true;
				Main.P1.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0f, -1.65f));
				Main.P1.Character.TaskPlayAnimLoop("random@drunk_driver_2", "cardrunksex_loop_m", -1);
				Main.P2.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(-0.8f, -0.07f, -0.9f));
				Main.P2.Character.Heading = Main.P1.Character.Heading;
				Main.P2.Character.TaskPlayAnimLoop("random@drunk_driver_2", "cardrunksex_loop_f", -1);
				SpawningProp("prop_patio_lounger1", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.3f, 0f, 0f)), new Vector3(0f, 0f, Main.P1.Character.Heading - 90f), ref prop1, dynamic: true, placeOnGround: true, 0.65f);
				propsSpawned = true;
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: true);
				Main.P1.Character.PlayAmbientSpeech1("SEX_GENERIC", immediately: true);
				Wait(500);
				Game.FadeScreenIn(500);
			}
			else if (sexType == SexType.PoleDance)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				OtherHelper.SetFollowPedCamViewMode(0);
				Wait(1000);
				SpawningProp("prop_strip_pole_01", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 1.5f, 0f)), ref prop1, dynamic: false);
				propsSpawned = true;
				Main.P2.Character.SetNoCollision(prop1, toggle: true);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P2.Character.FreezePosition = true;
				Main.P1.Character.FreezePosition = true;
				DateTime now = DateTime.Now;
				do
				{
					Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.13f, 1.1f, -1f));
					Main.P2.Character.Heading = Main.P1.Character.Heading + 120f;
					Wait(250);
					if (DateTime.Now.Subtract(now).TotalMilliseconds > 10000.0)
					{
						UI.Notify(TextSetting.of_Notify_Timeout);
						Game.FadeScreenIn(500);
						StageEnd();
						return;
					}
				}
				while (prop1.Position.DistanceTo(Main.P2.Character.GetBoneCoord(Bone.IK_L_Hand)) < 1.047f || prop1.Position.DistanceTo(Main.P2.Character.GetBoneCoord(Bone.IK_L_Hand)) > 1.1f);
				Main.P2.Character.FreezePosition = false;
				OtherHelper.SetFollowPedCamViewMode(4);
				Game.FadeScreenIn(500);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@pole_dance@pole_enter", "pd_enter", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@pole_dance@pole_dance1", "pd_dance_01", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@pole_dance@pole_dance2", "pd_dance_02", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@pole_dance@pole_dance3", "pd_dance_03", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@pole_dance@pole_exit", "pd_exit", -1, ref ImmediateStopSex, Line: true);
				ImmediateStopSex = true;
			}
			else if (sexType == SexType.RewardDance)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				OtherHelper.SetFollowPedCamViewMode(0);
				Wait(1000);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P1.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 1.5f, -1f));
				Main.P2.Character.Heading = Main.P1.Character.Heading + 100f;
				Wait(250);
				OtherHelper.SetFollowPedCamViewMode(4);
				Game.FadeScreenIn(500);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@private_dance@idle", "priv_dance_idle", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@private_dance@part1", "priv_dance_p1", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@private_dance@part2", "priv_dance_p2", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@private_dance@part3", "priv_dance_p3", -1, ref ImmediateStopSex, Line: true);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@private_dance@exit", "priv_dance_exit", -1, ref ImmediateStopSex, Line: true);
				ImmediateStopSex = true;
			}
			else if (sexType == SexType.ExclusiveDanceSingle)
			{
				Game.FadeScreenOut(500);
				Wait(500);
				OtherHelper.SetFollowPedCamViewMode(0);
				Wait(1000);
				SpawningProp("ex_mp_h_off_chairstrip_01", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, -0.1f, -1.1f)), new Vector3(0f, 0f, Main.P1.Character.Heading + 180f), ref prop1, dynamic: true, placeOnGround: true, 1f);
				propsSpawned = true;
				Main.P2.Character.SetNoCollision(prop1, toggle: true);
				Main.P1.Character.FreezePosition = true;
				Main.P1.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0f, -1.5f));
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.65f, 0.53f, -1f));
				Main.P2.Character.Heading = Main.P1.Character.Heading + 90f;
				Wait(250);
				OtherHelper.SetFollowPedCamViewMode(4);
				Game.FadeScreenIn(500);
				Main.P1.Character.TaskPlayAnimLoop("mini@strip_club@lap_dance@ld_girl_a_accept", "ld_girl_a_accept_m", -1);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_accept", "ld_girl_a_accept_f", -1, ref ImmediateStopSex, Line: true, "ld_girl_a_accept_m");
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_song_a_p1", "ld_girl_a_song_a_p1_m", -1, ref ImmediateStopSex);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_song_a_p1", "ld_girl_a_song_a_p1_f", -1, ref ImmediateStopSex, Line: true, "ld_girl_a_song_a_p1_m");
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_song_a_p2", "ld_girl_a_song_a_p2_m", -1, ref ImmediateStopSex);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_song_a_p2", "ld_girl_a_song_a_p2_f", -1, ref ImmediateStopSex, Line: true, "ld_girl_a_song_a_p2_m");
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_song_a_p3", "ld_girl_a_song_a_p3_m", -1, ref ImmediateStopSex);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_song_a_p3", "ld_girl_a_song_a_p3_f", -1, ref ImmediateStopSex, Line: true, "ld_girl_a_song_a_p3_m");
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_exit", "ld_girl_a_exit_m", -1, ref ImmediateStopSex);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance@ld_girl_a_exit", "ld_girl_a_exit_f", -1, ref ImmediateStopSex, Line: true, "ld_girl_a_exit_m");
				ImmediateStopSex = true;
			}
			else
			{
				if (sexType != SexType.ExclusiveDanceDouble)
				{
					return;
				}
				Game.FadeScreenOut(500);
				Wait(500);
				OtherHelper.SetFollowPedCamViewMode(0);
				Wait(1000);
				Main.P2.Character.Clone();
				Ped[] nearbyPeds = World.GetNearbyPeds(Main.P2.Character.Position, 3f, Main.P2.Character.Model);
				for (int i = 0; i < nearbyPeds.Length; i++)
				{
					if (nearbyPeds[i].Handle != Main.P2.Character.Handle)
					{
						cloneGirl = nearbyPeds[i];
					}
				}
				SpawningProp("ex_mp_h_off_chairstrip_01", Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, -0.1f, -1.1f)), new Vector3(0f, 0f, Main.P1.Character.Heading + 180f), ref prop1, dynamic: true, placeOnGround: true, 1f);
				propsSpawned = true;
				Main.P2.Character.SetNoCollision(prop1, toggle: true);
				cloneGirl.SetNoCollision(prop1, toggle: true);
				Main.P2.Character.Task.LookAt(Main.P1.Character);
				cloneGirl.Task.LookAt(Main.P1.Character);
				Main.P1.Character.FreezePosition = true;
				Main.P1.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0f, 0f, -1.5f));
				Main.P2.Character.FreezePosition = true;
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.645f, 0.62f, -0.5f));
				cloneGirl.FreezePosition = true;
				cloneGirl.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(-0.645f, 0.62f, -0.5f));
				Main.P1.Character.Heading = prop1.Heading + 180f;
				Main.P2.Character.Heading = Main.P1.Character.Heading + 45f;
				cloneGirl.Heading = Main.P1.Character.Heading - 45f;
				Main.P2.Character.FreezePosition = false;
				cloneGirl.FreezePosition = false;
				OtherHelper.SetFollowPedCamViewMode(4);
				Game.FadeScreenIn(500);
				Main.P1.Character.TaskPlayAnimLoop("mini@strip_club@lap_dance_2g@ld_2g_accept", "ld_2g_accept_m", -1);
				cloneGirl.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_accept", "ld_2g_accept_s1", -1, ref ImmediateStopSex, Line: false, "", 512);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_accept", "ld_2g_accept_s2", -1, ref ImmediateStopSex, Line: true, "ld_2g_accept_m", 512);
				Main.P2.Character.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(0.19f, 0.745f, -0.5f));
				cloneGirl.Position = Main.P1.Character.GetOffsetInWorldCoords(new Vector3(-0.25f, 0.745f, -0.5f));
				Main.P2.Character.Heading = Main.P1.Character.Heading + 180f;
				cloneGirl.Heading = Main.P1.Character.Heading - 180f;
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p1", "ld_2g_p1_m", -1, ref ImmediateStopSex);
				cloneGirl.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p1", "ld_2g_p1_s1", -1, ref ImmediateStopSex, Line: false, "", 512);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p1", "ld_2g_p1_s2", -1, ref ImmediateStopSex, Line: true, "ld_2g_p1_m", 512);
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p2", "ld_2g_p2_m", -1, ref ImmediateStopSex);
				cloneGirl.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p2", "ld_2g_p2_s1", -1, ref ImmediateStopSex, Line: false, "", 512);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p2", "ld_2g_p2_s2", -1, ref ImmediateStopSex, Line: true, "ld_girl_a_song_a_p2_m", 512);
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p3", "ld_2g_p3_m", -1, ref ImmediateStopSex);
				cloneGirl.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p3", "ld_2g_p3_s1", -1, ref ImmediateStopSex, Line: false, "", 512);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_p3", "ld_2g_p3_s2", -1, ref ImmediateStopSex, Line: true, "ld_2g_p3_m", 512);
				Main.P1.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_exit", "ld_2g_exit_m", -1, ref ImmediateStopSex);
				cloneGirl.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_exit", "ld_2g_exit_s1", -1, ref ImmediateStopSex, Line: false, "", 512);
				Main.P2.Character.TaskPlayAnim("mini@strip_club@lap_dance_2g@ld_2g_exit", "ld_2g_exit_s2", -1, ref ImmediateStopSex, Line: true, "ld_2g_exit_m", 512);
				cloneGirl.MarkAsNoLongerNeeded();
				cloneGirl.Delete();
				ImmediateStopSex = true;
			}
		}
		catch (Exception ex)
		{
			UI.Notify($"初始化性爱失败: {ex.Message}");
		}
	}

	private void SexSpeedChanges()
	{
		try
		{
			if (sexType == SexType.SexOralStand)
			{
				Main.P1.Character.SetEntityAnimCurrentSpeed("misscarsteal2pimpsex", "pimpsex_punter", sexSpeed);
				Main.P2.Character.SetEntityAnimCurrentSpeed("misscarsteal2pimpsex", "pimpsex_hooker", sexSpeed);
				Main.P2.Character.PlayAmbientSpeech2("SEX_ORAL_FEM", immediately: false);
			}
			else if (sexType == SexType.SexStand)
			{
				Main.P1.Character.SetEntityAnimCurrentSpeed("rcmpaparazzo_2", "shag_loop_a", sexSpeed);
				Main.P2.Character.SetEntityAnimCurrentSpeed("rcmpaparazzo_2", "shag_loop_poppy", sexSpeed);
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: false);
			}
			else if (sexType == SexType.Sex2Stand)
			{
				Main.P1.Character.SetEntityAnimCurrentSpeed("misscarsteal2pimpsex", "shagloop_pimp", sexSpeed);
				Main.P2.Character.SetEntityAnimCurrentSpeed("misscarsteal2pimpsex", "shagloop_hooker", sexSpeed);
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: false);
			}
			else if (sexType == SexType.SexOralSit)
			{
				Main.P1.Character.SetEntityAnimCurrentSpeed("mini@prostitutes@sexnorm_veh", "bj_loop_male", sexSpeed);
				Main.P2.Character.SetEntityAnimCurrentSpeed("mini@prostitutes@sexnorm_veh", "bj_loop_prostitute", sexSpeed);
				Main.P2.Character.PlayAmbientSpeech2("SEX_ORAL_FEM", immediately: false);
			}
			else if (sexType == SexType.SexOral2Sit)
			{
				Main.P1.Character.SetEntityAnimCurrentSpeed("mini@prostitutes@sexnorm_veh", "bj_loop_male", sexSpeed);
				Main.P2.Character.SetEntityAnimCurrentSpeed("mini@prostitutes@sexnorm_veh", "bj_loop_prostitute", sexSpeed);
				Main.P2.Character.PlayAmbientSpeech2("SEX_ORAL_FEM", immediately: false);
			}
			else if (sexType == SexType.SexSit)
			{
				Main.P1.Character.SetEntityAnimCurrentSpeed("mini@prostitutes@sexnorm_veh", "sex_loop_male", sexSpeed);
				Main.P2.Character.SetEntityAnimCurrentSpeed("mini@prostitutes@sexnorm_veh", "sex_loop_prostitute", sexSpeed);
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: false);
			}
			else if (sexType == SexType.SexLie)
			{
				Main.P1.Character.SetEntityAnimCurrentSpeed("random@drunk_driver_2", "cardrunksex_loop_m", sexSpeed);
				Main.P2.Character.SetEntityAnimCurrentSpeed("random@drunk_driver_2", "cardrunksex_loop_f", sexSpeed);
				Main.P2.Character.PlayAmbientSpeech2("SEX_GENERIC", immediately: false);
			}
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex, "SexSpeedChanges - 性爱速度变化");
		}
	}

	private static void SpawningProp(string name, Vector3 position, ref Prop prop, bool dynamic = true, bool placeOnGround = true, float correctZ = 0f)
	{
		Model model = null;
		try
		{
			model = new Model(name);
			bool flag = model.Request(2000);
			DateTime now = DateTime.Now;
			if (model.IsInCdImage && model.IsValid && flag)
			{
				prop = World.CreateProp(model, position, dynamic, placeOnGround);
			}
			if (prop != null)
			{
				position.Z += correctZ;
				if ((position - prop.Position).Z >= 1.03f || (position - prop.Position).Z <= 0.97f)
				{
					prop.Position = prop.GetOffsetInWorldCoords(new Vector3(0f, 0f, (position - prop.Position).Z));
					while ((position - prop.Position).Z >= 1.03f || (position - prop.Position).Z <= 0.97f)
					{
						Wait(50);
						if ((position - prop.Position).Z > 1.03f)
						{
							prop.Position = prop.GetOffsetInWorldCoords(new Vector3(0f, 0f, 0.05f));
						}
						else
						{
							prop.Position = prop.GetOffsetInWorldCoords(new Vector3(0f, 0f, -0.05f));
						}
						if (DateTime.Now.Subtract(now).TotalMilliseconds >= 3000.0)
						{
							break;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex, "SpawningProp - 生成道具(无旋转)");
		}
		finally
		{
			// 确保Model被正确释放
			if (model != null)
			{
				model.MarkAsNoLongerNeeded();
			}
		}
	}

	private static void SpawningProp(string name, Vector3 position, Vector3 rotation, ref Prop prop, bool dynamic = true, bool placeOnGround = true, float correctZ = 0f)
	{
		Model model = null;
		try
		{
			model = new Model(name);
			bool flag = model.Request(2000);
			DateTime now = DateTime.Now;
			if (model.IsInCdImage && model.IsValid && flag)
			{
				prop = World.CreateProp(model, position, rotation, dynamic, placeOnGround);
			}
			if (prop != null)
			{
				position.Z += correctZ;
				if ((position - prop.Position).Z >= 1.03f || (position - prop.Position).Z <= 0.97f)
				{
					prop.Position = prop.GetOffsetInWorldCoords(new Vector3(0f, 0f, (position - prop.Position).Z));
					while ((position - prop.Position).Z >= 1.03f || (position - prop.Position).Z <= 0.97f)
					{
						Wait(50);
						if ((position - prop.Position).Z > 1.03f)
						{
							prop.Position = prop.GetOffsetInWorldCoords(new Vector3(0f, 0f, 0.05f));
						}
						else
						{
							prop.Position = prop.GetOffsetInWorldCoords(new Vector3(0f, 0f, -0.05f));
						}
						if (DateTime.Now.Subtract(now).TotalMilliseconds >= 3000.0)
						{
							break;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex, "SpawningProp - 生成道具(有旋转)");
		}
		finally
		{
			// 确保Model被正确释放
			if (model != null)
			{
				model.MarkAsNoLongerNeeded();
			}
		}
	}

	public static void StageEnd()
	{
		try
		{
			if (cloneGirl != null)
			{
				cloneGirl.MarkAsNoLongerNeeded();
				cloneGirl.Delete();
				cloneGirl = null;
			}
			
			// 优化：只在Prop被创建时才清理
			if (propsSpawned)
			{
				if (prop1 != null)
				{
					prop1.MarkAsNoLongerNeeded();
					prop1.Delete();
					prop1 = null;
				}
				if (prop2 != null)
				{
					prop2.MarkAsNoLongerNeeded();
					prop2.Delete();
					prop2 = null;
				}
				propsSpawned = false;
			}
			
			if (Main.P1.Character != null)
			{
				Main.P1.Character.FreezePosition = false;
			}
			if (Main.P2.Character != null)
			{
				Main.P2.Character.FreezePosition = false;
				Main.P2.Character.SetNoCollision(Main.P1.Character, toggle: false);
				Main.P2.Character.Task.ClearAll();
			}
			if (Main.P1.Character != null)
			{
				Main.P1.Character.Task.ClearAll();
			}
			
			status = Status.None;
			sexType = SexType.None;
			Main.m_Status = Main.MaleStatus.None;
			
			if (Main.P2.Character != null && Main.P2.Character.IsDead)
			{
				Main.f_Status = Main.FemaleStatus.None;
			}
			
			if (Main.P1.skin.Voice != string.Empty && Main.P1.skin.Voice != null)
			{
				Main.P1.Character.SetVoice(Main.P1.skin.Voice);
			}
			if (Main.P2.skin.Voice != string.Empty && Main.P2.skin.Voice != null)
			{
				Main.P2.Character.SetVoice(Main.P2.skin.Voice);
			}
		}
		catch (Exception ex)
		{
			UI.Notify($"结束性爱失败: {ex.Message}");
		}
	}
}
